package com.zzzn.rhtx.service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.zzzn.rhtx.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;

@Slf4j
@Service
public class RhtxClient {

    public static final int SUCCESS_STATUS = 200;


    @Value("${rhtx.username}")
    private String userName;

    @Value("${rhtx.password}")
    private String passWord;

    @Value("${rhtx.id}")
    private int id;

    @Value("${rhtx.ip}")
    private String ip;


    @Autowired
    private RestTemplate restTemplate;

    public volatile String token;

    public volatile String flowID;



    /**
     * 用户登录接口
     * POST  IP:9005/idispatch/login
     */
    @PostConstruct
    public void login() {
        String url = "http://" + ip + ":9005/idispatch/login";
        LoginRequestDo requestDo = LoginRequestDo.builder().request(LoginDo.builder().userName(userName).
                userPwd(passWord).id(id).type("UserLogin").build()).build();
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getOneHeaders()), String.class);
            String body = exchange.getBody();
            LoginResponse loginResponse = JSONObject.parseObject(body, LoginResponse.class);
            log.info("#login.response:{}", loginResponse);
            assert loginResponse.getTokensign() != null;
            token = loginResponse.getTokensign();
        } catch (Exception e) {
            log.error("#login.error:", e);
        }
    }

    /**
     * 连接保活，也就是保持心跳
     * 心跳超时时间为30 s，建议保活时间为10s
     * GET  IP:9005/idispatch/keepconnect
     */
    @Scheduled(cron = "${rhtx.cron-keepconnect}") //每10s连接一次
    public void keepConnect() {
        String url = "http://" + ip + ":9005/idispatch/keepconnect";
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.GET, new HttpEntity<>(null, getHeaders()), String.class);
            String body = exchange.getBody();
            KeepConnectResponse response = JSONObject.parseObject(body, KeepConnectResponse.class);
            if (response.getStatus() == SUCCESS_STATUS) {
                log.info("keep connect rtn success");
            } else {
                log.info("keep connect rtn fail");
            }
        } catch (Exception e) {
            //如果保活失败，需要重新登录
            forceLogout();
            login();
            log.error("#keepConnect.error:", e);
        }
    }

    /**
     * 轮询方式
     * Get IP:9005/idispatch/poll
     *
     * @return
     */
    @Scheduled(cron = "${rhtx.cron-poll}") //每10s连接一次
    public MakeCallPollResponse poll() {
        String url = "http://" + ip + ":9005/idispatch/poll";
        MakeCallPollResponse response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.GET, new HttpEntity<>(null, getHeaders()), String.class);
            String body = exchange.getBody();
            response = JSONObject.parseObject(body, MakeCallPollResponse.class);
        } catch (Exception e) {
            log.error("#poll.error:", e);
        }
        log.info("#poll.response:{}", response);
        return response;
    }

    /**
     * 用户登出
     * GET  IP:9005/idispatch/userlogout
     */
    public KeepConnectResponse userLogout() {
        String url = "http://" + ip + ":9005/idispatch/userlogout";
        KeepConnectResponse response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.GET, new HttpEntity<>(null, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), KeepConnectResponse.class);
        } catch (Exception e) {
            log.error("#userLogout.error", e);
        }

        if (response.getStatus() == SUCCESS_STATUS) {
            log.info("user logout rtn success");
        } else {
            log.info("user logout rtn fail");
        }
        return response;
    }

    /**
     * 用户强制登出
     * Post  IP:9005/idispatch/forcelogout
     */
    public KeepConnectResponse forceLogout() {
        String url = "http://" + ip + ":9005/idispatch/forcelogout";
        ForceLogoutRequsetDo forceLogoutRequsetDo = ForceLogoutRequsetDo.builder().username(userName).
                userpwd(passWord).build();
        KeepConnectResponse response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(forceLogoutRequsetDo, getOneHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), KeepConnectResponse.class);
            if (response.getStatus() == SUCCESS_STATUS) {
                log.info("force logout rtn success");
            } else {
                log.info("force logout rtn fail");
            }
        } catch (Exception e) {
            log.error("#forceLogout.error:", e);
        }

        return response;
    }

    /**
     * 单呼
     * 3.GetVideoRtspUrl
     * POST  10.20.128.188:9005/idispatch/makecall
     *
     * @param requestDo
     * @return
     */
    public MakeCallResponse makeCall(MakeCallRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/makecall";
        MakeCallResponse response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), MakeCallResponse.class);
        } catch (Exception e) {
            log.error("#makeCall.error:", e);
        }
        log.info("#makeCall.response:{},req:{}", response, requestDo);
        return response;
    }

    /**
     * 获取视频通话图像
     * @param requestDo
     * @return
     */
    public MakeCallResponse getVideoRtspUrl(GetVideoRtspUrlRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/makecall";
        MakeCallResponse response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), MakeCallResponse.class);
        } catch (Exception e) {
            log.error("#getVideoRtspUrl.error:", e);
        }
        log.info("#getVideoRtspUrl.response:{},req:{}", response, requestDo);
        return response;
    }

    /**
     * 选呼
     * @param requestDo
     * @return
     */
    public MakeCallResponse selectCall(SelectCallRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/makecall";
        MakeCallResponse response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), MakeCallResponse.class);
        } catch (Exception e) {
            log.error("#selectCall.error:", e);
        }
        log.info("#selectCall.response:{},req:{}", response, requestDo);
        return response;
    }

    /**
     * 视频会商接口，需要调用两次，1次分屏，1次混流
     */
    public MakeCallResponse setMeetVideoMix(SetMeetVideoMixRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/makecall";
        MakeCallResponse response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), MakeCallResponse.class);
        } catch (Exception e) {
            log.error("#setMeetVideoMix.error:", e);
        }
        log.info("#setMeetVideoMix.response:{},req:{}", response, requestDo);
        return response;
    }

    /**
     * 轮询呼叫
     * 1对多
     *
     * @param requestDo
     * @return
     */
    public MakeCallResponse makeCallPoll(MakeCallPollRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/makecall";
        MakeCallResponse response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), MakeCallResponse.class);
            flowID = response.getFlowID();
        } catch (Exception e) {
            log.error("#makeCallPoll.error:", e);
        }

        log.info("#makeCallPoll.response:{}", response);
        return response;
    }


    /**
     * 单呼挂断
     * POST  10.20.128.188:9005/idispatch/clearcall
     *
     * @return
     */
    public BaseResult clearCall() {
        String url = "http://" + ip + ":9005/idispatch/clearcall";
        BaseResult response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(null, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), BaseResult.class);
        } catch (Exception e) {
            log.error("#clearCall.error:", e);
        }

        log.info("#clearCall.response:{}", response);
        return response;
    }

    /**
     * 结束轮询呼叫 1对多呼叫
     *
     * @return
     */
    public MakeCallResponse endPollCall() {
        EndPollCallRequestDo requestDo = EndPollCallRequestDo.builder().request(EndPollCallRequestDo.EndPollCallRequest.builder()
                .id("100000").type("EndPollCall").flowID(flowID).build()).build();
        String url = "http://" + ip + ":9005/idispatch/makecall";
        MakeCallResponse response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), MakeCallResponse.class);
        } catch (Exception e) {
            log.error("#endPollCall.error:", e);
        }

        log.info("#endPollCall.response:{}", response);
        return response;
    }

    /**
     * 2.将成员拉入会议
     * 加入会议
     * <p>
     * SetMeetVideoMix 视频混码，成员共享的视频
     * POST  10.20.128.188:9005/idispatch/makecall
     *
     * @param requestDo
     * @return
     */
    public BaseResult joinMeetCall(JoinMeetCallRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/makecall";
        BaseResult response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);

            response = JSONObject.parseObject(exchange.getBody(), BaseResult.class);
        } catch (Exception e) {
            log.error("#joinMeetCall.error:", e);
        }

        log.info("#joinMeetCall.response:{},req:{}", response, requestDo);
        return response;
    }


    /**
     * 通过对应通话id查询通话录音
     * POST  IP:9005/idispatch/record
     *
     * @param requestDo
     * @return
     */
    public BaseResult getSpecifiedRec(RecordRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/record";
        BaseResult response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), BaseResult.class);
        } catch (Exception e) {
            log.error("#getSpecifiedRec.error:", e);
        }

        log.info("#getSpecifiedRec.response:{}", response);
        return response;
    }

    /**
     * 同步获取通话记录
     * POST  IP:9005/idispatch/callrecord
     *
     * @param requestDo
     * @return
     */
    public CallRecordResponse callRecord(CallRecordRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/callrecord";
        CallRecordResponse response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);

            response = JSONObject.parseObject(exchange.getBody(), CallRecordResponse.class);
        } catch (Exception e) {
            log.error("#callRecord.error:", e);
        }

        log.info("#callRecord.response:{}", response);
        return response;
    }

    /**
     * 视频会商流程：
     * CreateMeet:视频会议            ——>  JoinMeetCall  将成员拉入会议
     * ——>GetVideoRtspUrl 获取话机视频流 ——>SetMeetVideoMix 视频混码，成员共享的视频         ——>MeetKick关闭会议
     * <p>
     * 1.创建会议
     * POST  10.20.128.188:9005/idispatch/makecall
     *
     * @param requestDo
     * @return
     */
    public MakeCallResponse createMeet(CreateMeetingRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/makecall";
        MakeCallResponse response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), MakeCallResponse.class);
        } catch (Exception e) {
            log.error("#createMeet.error:", e);
        }

        log.info("#createMeet.response:{},req:{}", response, requestDo);
        return response;
    }

    /**
     * 结束会议
     * POST  10.20.128.188:9005/idispatch/makecall
     *
     * @param requestDo
     * @return
     */
    public BaseResult endMeet(EndMeetingRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/makecall";
        BaseResult response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), BaseResult.class);
        } catch (Exception e) {
            log.error("#endMeet.error:", e);
        }

        log.info("#endMeet.response:{},req:{}", response, requestDo);
        return response;
    }


    /**
     * 修改会议
     * POST  10.20.128.188:9005/idispatch/makecall
     *
     * @param requestDo
     * @return
     */
    public BaseResult modifyMeet(UpdateMeetingRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/makecall";
        BaseResult response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), BaseResult.class);
        } catch (Exception e) {
            log.error("#modifyMeet.error:", e);
        }

        log.info("#modifyMeet.response:{}", response);
        return response;
    }

    /**
     * 4.3.11会议发言
     * POST  10.20.128.188:9005/idispatch/makecall
     *
     * @param requestDo
     * @return
     */
    public BaseResult meetAllowSpeak(MeetingSpeakRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/makecall";
        BaseResult response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), BaseResult.class);
        } catch (Exception e) {
            log.error("#meetAllowSpeak.error:", e);
        }

        log.info("#meetAllowSpeak.response:{}", response);
        return response;
    }

    /**
     * 4.3.12会议禁言
     * POST  10.20.128.188:9005/idispatch/makecall
     *
     * @param requestDo
     * @return
     */
    public BaseResult meetBanSpeak(MeetingSpeakRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/makecall";
        BaseResult response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);
            response = JSONObject.parseObject(exchange.getBody(), BaseResult.class);
        } catch (Exception e) {
            log.error("#meetBanSpeak.error", e);
        }

        log.info("#meetBanSpeak.response:{}", response);
        return response;
    }

    /**
     * 4.3.13会议踢出
     * MeetKick关闭会议
     * POST  10.20.128.188:9005/idispatch/makecall
     *
     * @param requestDo
     * @return
     */
    public BaseResult meetKick(MeetingSpeakRequestDo requestDo) {
        String url = "http://" + ip + ":9005/idispatch/makecall";
        BaseResult response = null;
        try {
            ResponseEntity<String> exchange = restTemplate.exchange(url,
                    HttpMethod.POST, new HttpEntity<>(requestDo, getHeaders()), String.class);

            response = JSONObject.parseObject(exchange.getBody(), BaseResult.class);
        } catch (Exception e) {
            log.error("#meetKick.error:", e);
        }

        log.info("#meetKick.response:{},req:{}", response, requestDo);
        return response;
    }


    /**
     * 统一获取header
     *
     * @return
     */
    private HttpHeaders getHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        if (StringUtils.isEmpty(token)) {
            login();
        }
        if (!StringUtils.isEmpty(token)) {
            headers.add("Authorization", token);
        }
        return headers;
    }

    /**
     * 只需要一个单独的类型
     *
     * @return
     */
    private HttpHeaders getOneHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        return headers;
    }


}
